home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / 3DGPL.ZIP / 3DGPL / CODE / GRAPHICS / GRP-POLY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-22  |  12.5 KB  |  321 lines

  1. /** 3DGPL *************************************************\
  2.  *  (8bit deep bitmap)                                    *
  3.  *  2D graphics and 2D clipping extentions for shaded     *
  4.  *  and textured polygons (has to be linked with regular  *
  5.  *  routines).                                            *
  6.  *                                                        *
  7.  *  Defines:                                              *
  8.  *   G_ambient_polygon       regular polygon;             *
  9.  *   G_shaded_polygon        shaded polygon;              *
  10.  *   G_textured_polygon      textured polygon.            *
  11.  *                                                        *
  12.  *  Internals:                                            *
  13.  *   GI_scan                 scanning an edge;            *
  14.  *   GI_boarder_array_init   init left/right boundaries.  *
  15.  *                                                        *
  16.  *  (6/1995) By Sergei Savchenko. (savs@cs.mcgill.ca).    *
  17.  *  Copyright (c) 1995 Sergei Savchenko.                  *
  18.  *  THIS SOURCE CODE CAN'T BE USED FOR COMERCIAL PURPOSES *
  19.  *  WITHOUT AUTHORISATION                                 *
  20. \**********************************************************/
  21.  
  22. #include <limits.h>                         /* INT_MAX/INT_MIN */
  23. #include "../hardware/hardware.h"           /* hardware specific stuff */
  24. #include "../clipper/clipper.h"             /* 2D clipping */
  25. #include "../graphics/graphics.h"           /* 2D macros */  
  26. #include "../trans/trans.h"                 /* T_LOG_FOCUS */
  27.  
  28. extern unsigned char *G_buffer;             /* the bitmap's bits */
  29.  
  30. int G_start[HW_SCREEN_Y_SIZE];              /* polygon's */
  31. int G_end[HW_SCREEN_Y_SIZE];                /* horizontal boundaries */
  32. int G_miny,G_maxy;                          /* vertical boundaries */
  33.  
  34. #define G_P      10                         /* fixed point math prcision */
  35. #define G_LINEAR 32                         /* linearely interpolate for */
  36.  
  37. signed_32_bit G_0_start[HW_SCREEN_Y_SIZE];  /* contains [32-G_P].[G_P] values */
  38. signed_32_bit G_0_end[HW_SCREEN_Y_SIZE];    /* this thingie is to work faster */
  39. signed_32_bit G_1_start[HW_SCREEN_Y_SIZE];  /* then multidimensional array */
  40. signed_32_bit G_1_end[HW_SCREEN_Y_SIZE];    /* hope so, */
  41. signed_32_bit G_2_start[HW_SCREEN_Y_SIZE];
  42. signed_32_bit G_2_end[HW_SCREEN_Y_SIZE];
  43.  
  44. signed_32_bit *G_rest_start[C_MAX_DIMENSIONS]={G_0_start,G_1_start,G_2_start};
  45. signed_32_bit *G_rest_end[C_MAX_DIMENSIONS]={G_0_end,G_1_end,G_2_end};
  46.  
  47. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  48.  *  INTERNAL: Scan converting a N dimensional line.      *
  49.  *  ---------                                            *  
  50. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  51.  
  52. void GI_scan(int *edges,int dimension,int skip)
  53. {
  54.  signed_32_bit cur_v[C_MAX_DIMENSIONS];     /* initial values for Z+ dims */
  55.  signed_32_bit inc_v[C_MAX_DIMENSIONS];     /* increment for Z+ dimensions */
  56.  signed_32_bit tmp;
  57.  int dx,dy,long_d,short_d;
  58.  register int d,add_dh,add_dl;              
  59.  register int inc_xh,inc_yh,inc_xl,inc_yl;  
  60.  int x,y,i,j;
  61.  int *v1,*v2;                               /* first and second vertices */
  62.  
  63.  v1=edges; edges+=skip; v2=edges;           /* length ints in each */
  64.  
  65.  if(C_line_y_clipping(&v1,&v2,dimension))   /* vertical clipping */
  66.  {
  67.   dx=*v2++; dy=*v2++;                       /* extracting 2-D coordinates */
  68.   x=*v1++; y=*v1++;                         /* v2/v1 point remaining dim-2 */
  69.   dimension-=2; 
  70.  
  71.   if(y<G_miny) G_miny=y;
  72.   if(y>G_maxy) G_maxy=y;
  73.   if(dy<G_miny) G_miny=dy;
  74.   if(dy>G_maxy) G_maxy=dy;                  /* updating vertical size */
  75.  
  76.   dx-=x; dy-=y;                             /* ranges */
  77.  
  78.   if(dx<0){dx=-dx; inc_xh=-1; inc_xl=-1;}   /* making sure dx and dy >0 */
  79.   else    {        inc_xh=1;  inc_xl=1; }   /* adjusting increments */
  80.   if(dy<0){dy=-dy; inc_yh=-1; inc_yl=-1;}
  81.   else    {        inc_yh=1;  inc_yl=1; }
  82.  
  83.   if(dx>dy){long_d=dx;short_d=dy;inc_yl=0;} /* long range,&making sure either */
  84.   else     {long_d=dy;short_d=dx;inc_xl=0;} /* x or y is changed in L case */
  85.  
  86.   d=2*short_d-long_d;                       /* initial value of d */
  87.   add_dl=2*short_d;                         /* d adjustment for H case */
  88.   add_dh=2*short_d-2*long_d;                /* d adjustment for L case */
  89.  
  90.   for(i=0;i<dimension;i++)                  /* for all remaining dimensions */
  91.   {
  92.    tmp=v1[i]; tmp<<=G_P; cur_v[i]=tmp;      /* f.p. start value */
  93.    tmp=v2[i]-v1[i]; tmp<<=G_P;              /* f.p. increment */
  94.    if(long_d>0) inc_v[i]=tmp/long_d;        /* if needed (non 0 lines) */
  95.   }
  96.  
  97.   for(i=0;i<=long_d;i++)                    /* for all points in longer range */
  98.   {
  99.    if(x<G_start[y])                         /* further then rightmost */
  100.    {
  101.     G_start[y]=x;                           /* the begining of scan line */
  102.     for(j=0;j<dimension;j++)
  103.      G_rest_start[j][y]=cur_v[j];            /* all other dimensions */
  104.    }
  105.  
  106.    if(G_end[y]<x)                           /* further the leftmost */
  107.    {
  108.     G_end[y]=x;                             /* the end of scan line */
  109.     for(j=0;j<dimension;j++)
  110.      G_rest_end[j][y]=cur_v[j];              /* and for other dimension */
  111.    }
  112.  
  113.    if(d>=0){x+=inc_xh;y+=inc_yh;d+=add_dh;} /* previous point was H type */
  114.    else    {x+=inc_xl;y+=inc_yl;d+=add_dl;} /* previous point was L type */
  115.    for(j=0;j<dimension;j++) 
  116.     cur_v[j]+=inc_v[j];                     /* for all other dimensions */
  117.   }
  118.  }
  119. }
  120.  
  121. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  122.  *  INTERNAL: Initialization of polygon boundaries.      *
  123.  *  ---------                                            *
  124. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  125.  
  126. void GI_boarder_array_init(void)
  127. {
  128.  G_miny=INT_MAX;                            /* polygon starts here */
  129.  G_maxy=INT_MIN;                            /* polygon ends here */
  130.  
  131.  HW_set_int(G_start,HW_SCREEN_Y_SIZE,INT_MAX);
  132.  HW_set_int(G_end,HW_SCREEN_Y_SIZE,INT_MIN);/* limiting values */
  133. }
  134.  
  135. /**********************************************************\
  136.  *  Rendering a polygon.                                  *
  137.  *  Accepts 2-tuples (X,Y) per vertex.                    *
  138. \**********************************************************/
  139.  
  140. void G_ambient_polygon(int *edges,int length,unsigned char colour)
  141. {
  142.  int new_edges[G_MAX_TUPLES];               /* verticaly clipped polygon */
  143.  int new_length;                            /* although no edges there yet */
  144.  register unsigned char *l_adr,*adr;        
  145.  register int beg,end,i;
  146.  
  147.  GI_boarder_array_init();                   /* initializing the arrays */
  148.  
  149.  new_length=C_polygon_x_clipping(edges,new_edges,2,length);
  150.  
  151.  for(i=0;i<new_length;i++)
  152.   GI_scan(&new_edges[i*2],2,2);             /* Searching polygon boarders */
  153.  
  154.  if(G_miny<=G_maxy)                         /* nothing to do? */
  155.  {
  156.   l_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE;   /* addr of 1st byte of 1st line */
  157.  
  158.   for(; G_miny<=G_maxy; G_miny++,
  159.       l_adr+=HW_SCREEN_X_SIZE)              /* rendering all lines */
  160.   {
  161.    adr=l_adr+(beg=G_start[G_miny]);         /* addr of the current line */
  162.    end=G_end[G_miny]-beg+1;                 /* ends here */
  163.  
  164.    HW_set_char((char*)adr,end,colour);      /* rendering single line */
  165.   }
  166.  }
  167. }
  168.  
  169. /**********************************************************\
  170.  *  Rendering an Interpolatively shaded polygon.          *
  171.  *  Accepts 3-tuples (X,Y,ColourIntensity) per vertex.    *
  172. \**********************************************************/
  173.  
  174. void G_shaded_polygon(int *edges,int length)
  175. {
  176.  int new_edges[G_MAX_SHADED_TUPLES];        /* verticaly clipped polygon */
  177.  int new_length;
  178.  register unsigned char *l_adr,*adr;        
  179.  register int beg,end,i;
  180.  register signed_32_bit cur_c,inc_c;        /* current colour and it's inc */
  181.  
  182.  GI_boarder_array_init();                   /* initializing the array */
  183.  
  184.  new_length=C_polygon_x_clipping(edges,new_edges,3,length);
  185.  
  186.  for(i=0;i<new_length;i++)
  187.   GI_scan(&new_edges[i*3],3,3);             /* Searching polygon boarders */
  188.  
  189.  if(G_miny<=G_maxy)                         /* nothing to do? */
  190.  {
  191.   l_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE;   /* addr of 1st byte of 1st line */
  192.  
  193.   for(; G_miny<=G_maxy; G_miny++,
  194.       l_adr+=HW_SCREEN_X_SIZE)              /* rendering all lines */
  195.   {
  196.    adr=l_adr+(beg=G_start[G_miny]);         /* addr of the current line */
  197.    end=G_end[G_miny];                       /* ends here */
  198.  
  199.    cur_c=G_0_start[G_miny];                 /* colour starts with this value */
  200.    inc_c=G_0_end[G_miny]-cur_c;
  201.    if(end>beg) inc_c/=end-beg+1;            /* f.p. increment */
  202.  
  203.    for(;beg<=end;beg++)                     /* render this lines */
  204.    {
  205.     *adr++=cur_c>>G_P;                      /* rendering single point */
  206.     cur_c+=inc_c;                           /* incrementing colour */
  207.    }
  208.   }
  209.  }
  210. }
  211.  
  212. /**********************************************************\
  213.  *  Rendering a texture rendered polygon.                 *
  214.  *  Accepts 4-tuples - (X,Y,TextureX,TextureY) per vertex.*
  215.  *  The applied texture is a 8bit deep square bitmap with:*
  216.  *                                                        *
  217.  *              log_texture_size=log texture_size         *
  218.  *                                  2                     *
  219. \**********************************************************/
  220.  
  221. void G_textured_polygon(int *edges,int length,int *O,int *u,int *v,
  222.             unsigned char *texture,int log_texture_size,
  223.                            int log_texture_scale
  224.                )
  225. {
  226.  int new_edges[G_MAX_SHADED_TUPLES];        /* verticaly clipped polygon */
  227.  int new_length;
  228.  signed_32_bit Vx,Vy,Vz;
  229.  signed_32_bit Ux,Uy,Uz;                    /* extracting vectors */
  230.  signed_32_bit x0,y0,z0;
  231.  signed_32_bit ui,uj,uc;
  232.  signed_32_bit vi,vj,vc;
  233.  signed_32_bit zi,zj,zc;                    /* back to texture coeficients */
  234.  signed_32_bit v0,u0;
  235.  signed_32_bit xx,yy,zz,zzz;                
  236.  int xstart,xend;
  237.  signed_32_bit txstart,tystart;
  238.  signed_32_bit txend,tyend;
  239.  signed_32_bit txinc,tyinc;
  240.  register unsigned char *g_adr,*adr;        
  241.  register int i,x,y;
  242.  signed_32_bit txtrmasc=(0x1<<(log_texture_size+G_P))-0x1;
  243.  log_texture_scale+=G_P;
  244.  
  245.  GI_boarder_array_init();                   /* initializing the array */
  246.  
  247.  new_length=C_polygon_x_clipping(edges,new_edges,4,length);
  248.  
  249.  for(i=0;i<new_length;i++)
  250.   GI_scan(&new_edges[i*4],2,4);             /* Searching polygon boarders */
  251.  
  252.  if(G_miny<=G_maxy)                         /* nothing to do? */
  253.  {
  254.   x0=O[0]; y0=O[1]; z0=O[2]; 
  255.   u0=O[3]<<G_P; v0=O[4]<<G_P;               /* world point <-> texture point */
  256.  
  257.   Vx=v[0]; Vy=v[1]; Vz=v[2];
  258.   Ux=u[0]; Uy=u[1]; Uz=u[2];                /* extracting vectors */
  259.  
  260.   ui=(Vz*y0)-(Vy*z0);
  261.   uj=(Vx*z0)-(Vz*x0);
  262.   uc=(Vy*x0)-(Vx*y0);
  263.   vi=(Uy*z0)-(Uz*y0);
  264.   vj=(Uz*x0)-(Ux*z0);
  265.   vc=(Ux*y0)-(Uy*x0);
  266.   zi=(Vy*Uz)-(Vz*Uy);
  267.   zj=(Vz*Ux)-(Vx*Uz);
  268.   zc=(Vx*Uy)-(Vy*Ux);                       /* back to texture */
  269.  
  270.   g_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE;   /* addr of 1st byte of 1st line */
  271.  
  272.   for(; G_miny<=G_maxy; G_miny++,
  273.       g_adr+=HW_SCREEN_X_SIZE)              /* rendering all lines */
  274.   {
  275.    xstart=G_start[G_miny];
  276.    adr=g_adr+xstart;
  277.    xstart-=HW_SCREEN_X_CENTRE;
  278.    x=xstart;
  279.    xend=G_end[G_miny]-HW_SCREEN_X_CENTRE;   
  280.    y=G_miny-HW_SCREEN_Y_CENTRE;
  281.  
  282.    xx=((y*uj)>>T_LOG_FOCUS)+uc;
  283.    yy=((y*vj)>>T_LOG_FOCUS)+vc;
  284.    zz=((y*zj)>>T_LOG_FOCUS)+zc;             /* valid for the hole run */
  285.  
  286.    if(( zzz=zz+((x*zi)>>T_LOG_FOCUS) )!=0) 
  287.    { 
  288.     txend=( (xx+ ((x*ui)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +u0;
  289.     tyend=( (yy+ ((x*vi)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +v0; 
  290.    }
  291.  
  292.    for(;xstart<xend;)
  293.    {
  294.     x+=G_LINEAR; if(x>xend) x=xend;         /* size of linear run */
  295.     txstart=txend;
  296.     tystart=tyend;
  297.  
  298.     if(( zzz=zz+((x*zi)>>T_LOG_FOCUS) )!=0) 
  299.     { 
  300.      txend=( (xx+ ((x*ui)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +u0;
  301.      tyend=( (yy+ ((x*vi)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +v0; 
  302.     }
  303.  
  304.     length=x-xstart;                        /* ends here */
  305.     if(length!=0) { txinc=(txend-txstart)/length; 
  306.             tyinc=(tyend-tystart)/length;
  307.           }
  308.  
  309.     for(;xstart<x;xstart++)                 /* linear run */
  310.     {
  311.      txstart&=txtrmasc; tystart&=txtrmasc;  /* wrap around */
  312.      *adr++=*(texture+((tystart>>G_P)<<log_texture_size)+(txstart>>G_P));
  313.      txstart+=txinc; tystart+=tyinc;        /* new position in the texture */
  314.     }
  315.    }
  316.   }
  317.  }
  318. }
  319.  
  320. /**********************************************************/
  321.